﻿using Microsoft.AspNetCore.Builder;
using System.Reflection;

namespace LS.Screening.Infrastructure
{
    public static class ModuleLoader
    {
        // 已经初始化的模块
        static readonly HashSet<Type> _initializedModules = new HashSet<Type>();

        // 已经初始化的程序集
        static readonly HashSet<Assembly> _initializedAssemblies = new HashSet<Assembly>();

        /// <summary>
        /// 运行模块
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="startupModuleType"></param>
        /// <returns></returns>
        public static List<AbpModule> Run(WebApplicationBuilder builder, Type startupModuleType)
        {
            //递归解析模块依赖
            CollectModules(startupModuleType);

            // 创建模块实例并调用 ConfigureServices
            var modules = _initializedModules
                .Select(type => Activator.CreateInstance(type) as AbpModule)
                .ToList();

            var serviceContext = new ServiceConfigurationContext(builder.Services, builder.Configuration);
            foreach (var module in modules)
            {
                module.ConfigureServices(serviceContext);
            }
            var applicationContenxt = new ApplicationInitializationContext(builder.Build());
            foreach (var module in modules)
            {
                module.OnApplicationInitialization(applicationContenxt);
            }
            return modules;
        }

        /// <summary>
        /// 递归解析模块依赖
        /// </summary>
        /// <param name="moduleType"></param>
        private static void CollectModules(Type moduleType)
        {
            if (_initializedModules.Contains(moduleType))
                return;
            _initializedModules.Add(moduleType);

            var dependsOnAttributes = moduleType.GetCustomAttributes<DependsOnAttribute>();
            foreach (var attr in dependsOnAttributes)
            {
                foreach (var dependency in attr.Dependencies)
                {
                    CollectModules(dependency);
                }
            }
            _initializedModules.Add(moduleType);
        }
    }
}
